Aim
At this experiment we want to determine what political and economic features can correlate with Life Expectancy in different countries and to determine how deeply can they correlate to make some assumptions. We will do this experiment with several features and several countries, and after that we will make some assumptions.
Choosing proper features
Dataset was taken from https://databank.worldbank.org/source/world-development-indicators#
Among 1440 features we have chosen only 42 that could correlate with life expectancy, but after analyzing gained data, we had to get rid of approximately 30 features because of the lack of data. However, we still have some features left that could correlate with chosen parameter:
GDP (per capita), Expense (% of GDP), Tech Industry Progress, Employment Ratio, Waged Workers Ratio, Health Expenditure and Binding Coverage.
Choosing countries
For this experiment we have decided to choose the countries with high-income (USA, Japan), middle-income (Ukraine, Tajikistan) and low-income (Mali, Haiti) to understand on what parameters depends life expectancy in countries with different money capital.
Approach
We will use the linear regression to see if there is a linear relation between the parameters we have chosen and use this knowledge to be able to decide what parameters really affect the life expectancy. Using linear regression we will determine the significance level of every parameter (its p-value), which will tells us either we will reject null hypothesis or no. Also, the R-squared will show us how good our model is. In other words, how good this linear relation is.
Hypothesis
So, we will have two hypothesis’, \(H_0\) (there is no correlation between these parameters) and \(H_1\) (there is at least one parameter that correlates).
\[
H_0 : \beta = \beta_0\ \;\;\;\; H_1: \beta \neq \beta_0
\]
# function to print data of experiment
print_model <- function(model, features) {
cat("Features:\t", features, "\nR-squared:\t", summary(model)$r.squared,
"\nP-values:\t", summary(model)$coefficients[,4])
}
Experimenting on High-level countries (USA, Japan)
We will try to find correlation life expectancy using the data set bellow. After this, we will decide what features can be chosen to determine what really effects this parameter of high-level countries. Some of the data is missed, but we do not take the first lines into consideration as we have 50-line data set, where each line corresponds to certain year.
USA
# read csv file
usa <- read.csv(file = 'data/data_usa.csv')
head(usa, 3)
Testing features
model <- lm(formula=life_expectancy ~ tech, data=usa)
print_model(model, "Tech")
Features: Tech
R-squared: 0.1488622
P-values: 3.228643e-12 0.0387192
model <- lm(formula=life_expectancy ~ employment_ratio + expense, data=usa)
print_model(model, "Employment Ratio + Expense")
Features: Employment Ratio + Expense
R-squared: 0.7191624
P-values: 7.876299e-18 6.411006e-09 6.106087e-05
model <- lm(formula=life_expectancy ~ waged_workers, data=usa)
print_model(model, "Waged Workers Ratio")
Features: Waged Workers Ratio
R-squared: 0.9197001
P-values: 3.913673e-07 9.298348e-16
model <- lm(formula=life_expectancy ~ health_expenditure, data=usa)
print_model(model, "Health Expenditure")
Features: Health Expenditure
R-squared: 0.8958492
P-values: 3.372309e-25 8.947952e-10
model <- lm(formula=life_expectancy ~ gdp, data=usa)
print_model(model, "GDP per Capita")
Features: GDP per Capita
R-squared: 0.9377959
P-values: 1.892913e-84 2.184632e-29
Japan
# read csv file
japan <- read.csv(file = 'data/data_japan.csv')
head(japan, 3)
Testing features
model <- lm(formula=life_expectancy ~ tech, data=japan)
print_model(model, "Tech")
Features: Tech
R-squared: 0.8630052
P-values: 1.099979e-18 3.60901e-13
model <- lm(formula=life_expectancy ~ employment_ratio + expense, data=japan)
print_model(model, "Employment Ratio + Expense")
Features: Employment Ratio + Expense
R-squared: 0.4751031
P-values: 1.916027e-11 0.0004164006 0.8136475
model <- lm(formula=life_expectancy ~ waged_workers, data=japan)
print_model(model, "Waged Workers Ratio")
Features: Waged Workers Ratio
R-squared: 0.9765257
P-values: 2.086609e-22 1.029833e-22
model <- lm(formula=life_expectancy ~ health_expenditure, data=japan)
print_model(model, "Health Expenditure")
Features: Health Expenditure
R-squared: 0.8207778
P-values: 4.332643e-27 9.379517e-08
model <- lm(formula=life_expectancy ~ gdp, data=japan)
print_model(model, "GDP per Capita")
Features: GDP per Capita
R-squared: 0.8471802
P-values: 1.156373e-68 2.18137e-20
Experimenting on Mid-level countries (Ukraine, Tajikistan)
We will try to find correlation life expectancy using the data set bellow. After this, we will decide what features can be chosen to determine what really effects this parameter of mid-level countries. Some of the data is missed, but we do not take the first lines into consideration as we have 50-line data set, where each line corresponds to certain year.
Ukraine
# read csv file
ukraine <- read.csv(file = 'data/data_ukraine.csv')
head(ukraine, 3)
Testing features
model <- lm(formula=life_expectancy ~ tech, data=ukraine)
print_model(model, "Tech")
Features: Tech
R-squared: 0.1407207
P-values: 2.251883e-28 0.04494516
model <- lm(formula=life_expectancy ~ binding_coverage, data=ukraine)
print_model(model, "Binding Coverage")
Features: Binding Coverage
R-squared: 0.7469041
P-values: 0.0003149671 0.0002879277
model <- lm(formula=life_expectancy ~ employment_ratio + expense, data=ukraine)
print_model(model, "Employment Ratio + Expense")
Features: Employment Ratio + Expense
R-squared: 0.7752642
P-values: 2.200717e-07 0.004536859 1.831055e-06
model <- lm(formula=life_expectancy ~ waged_workers, data=ukraine)
print_model(model, "Waged Workers Ratio")
Features: Waged Workers Ratio
R-squared: 0.4602053
P-values: 0.7514341 7.262422e-05
model <- lm(formula=life_expectancy ~ health_expenditure, data=ukraine)
print_model(model, "Health Expenditure")
Features: Health Expenditure
R-squared: 0.8110302
P-values: 8.51833e-18 1.47898e-07
model <- lm(formula=life_expectancy ~ gdp, data=ukraine)
print_model(model, "GDP per Capita")
Features: GDP per Capita
R-squared: 0.3723871
P-values: 1.835195e-44 0.0002084853
Tajikistan
# read csv file
tajikistan <- read.csv(file = 'data/data_tajikistan.csv')
head(tajikistan, 3)
Testing features
model <- lm(formula=life_expectancy ~ tech, data=tajikistan)
print_model(model, "Tech")
Features: Tech
R-squared: 0.0001222438
P-values: 6.558978e-12 0.9546065
model <- lm(formula=life_expectancy ~ binding_coverage, data=tajikistan)
print_model(model, "Binding Coverage")
Features: Binding Coverage
R-squared: 0.5333738
P-values: 0.06441052 0.06233742
model <- lm(formula=life_expectancy ~ employment_ratio + expense, data=tajikistan)
print_model(model, "Employment Ratio + Expense")
Features: Employment Ratio + Expense
R-squared: 0.9748906
P-values: 0.01706958 0.003234732 0.09977643
model <- lm(formula=life_expectancy ~ waged_workers, data=tajikistan)
print_model(model, "Waged Workers Ratio")
Features: Waged Workers Ratio
R-squared: 0.3875586
P-values: 0.05556629 0.0004036797
model <- lm(formula=life_expectancy ~ health_expenditure, data=tajikistan)
print_model(model, "Health Expenditure")
Features: Health Expenditure
R-squared: 0.9049081
P-values: 1.490146e-18 4.110342e-10
model <- lm(formula=life_expectancy ~ gdp, data=tajikistan)
print_model(model, "GDP per Capita")
Features: GDP per Capita
R-squared: 0.650548
P-values: 8.896529e-30 1.269416e-07
Experimenting on Low-level countries (Mali, Haiti)
We will try to find correlation life expectancy using the data set bellow. After this, we will decide what features can be chosen to determine what really effects this parameter of low-level countries. Some of the data is missed, but we do not take the first lines into consideration as we have 50-line data set, where each line corresponds to certain year.
Mali
# read csv file
mali <- read.csv(file = 'data/data_mali.csv')
head(mali, 3)
Testing features
model <- lm(formula=life_expectancy ~ binding_coverage, data=mali)
print_model(model, "Binding Coverage")
Features: Binding Coverage
R-squared: 0.8315655
P-values: 1.160222e-11 1.410876e-09
model <- lm(formula=life_expectancy ~ employment_ratio + expense, data=mali)
print_model(model, "Employment Ratio + Expense")
Features: Employment Ratio + Expense
R-squared: 0.2011274
P-values: 0.003418929 0.3809186 0.07368043
model <- lm(formula=life_expectancy ~ waged_workers, data=mali)
print_model(model, "Waged Workers Ratio")
Features: Waged Workers Ratio
R-squared: 0.962084
P-values: 0.2924288 5.281538e-20
model <- lm(formula=life_expectancy ~ health_expenditure, data=mali)
print_model(model, "Health Expenditure")
Features: Health Expenditure
R-squared: 0.5365706
P-values: 3.879104e-12 0.0003616868
model <- lm(formula=life_expectancy ~ gdp, data=mali)
print_model(model, "GDP per Capita")
Features: GDP per Capita
R-squared: 0.8639236
P-values: 9.028364e-42 1.498146e-21
Haiti
# read csv file
haiti <- read.csv(file = 'data/data_haiti.csv')
head(haiti, 3)
Testing features
model <- lm(formula=life_expectancy ~ tech, data=haiti)
print_model(model, "Tech")
Features: Tech
R-squared: 0.3541302
P-values: 1.231589e-28 0.0006614124
model <- lm(formula=life_expectancy ~ binding_coverage, data=haiti)
print_model(model, "Binding Coverage")
Features: Binding Coverage
R-squared: 0.6452332
P-values: 0.0004200059 0.001650783
model <- lm(formula=life_expectancy ~ employment_ratio, data=haiti)
print_model(model, "Employment Ratio")
Features: Employment Ratio
R-squared: 0.4111128
P-values: 8.24176e-11 0.0002364116
model <- lm(formula=life_expectancy ~ waged_workers, data=haiti)
print_model(model, "Waged Workers Ratio")
Features: Waged Workers Ratio
R-squared: 0.9644511
P-values: 2.658375e-21 2.28196e-20
model <- lm(formula=life_expectancy ~ health_expenditure, data=haiti)
print_model(model, "Health Expenditure")
Features: Health Expenditure
R-squared: 0.422701
P-values: 1.848818e-15 0.00258184
model <- lm(formula=life_expectancy ~ gdp, data=haiti)
print_model(model, "GDP per Capita")
Features: GDP per Capita
R-squared: 0.8581152
P-values: 7.013973e-58 3.930682e-21
Visualization part
In the above part, we have understood that Life expectancy is the most linearly dependent on such features as Health expenditure, Waged workers, GDP per capita, Employment ratio and Expense. It was found out based on the results of the majority of countries, where they are dependent.
Now the main aim of visualization part is to really see, compare the results with graphs, know interesting facts about our and other countries and make sure of the truth of the findings.
require(ggplot2)
library(ggplot2)
library(plotly)
library(dgof)
library('plot.matrix')
Matrix for tendency of Mean, Mode, Meadian of life expectancy of the countries
Data have been collected through 30-50 years
According to this matrix we can see general tendency of life expectancy of the countries and place them by value of this indicator(starting from longest): Japan, USA, Ukraine, Tajikistan, Haiti, Mali
get_mode <- function(v) {
uniqv <- unique(v)
uniqv[which.max(tabulate(match(v, uniqv)))]
}
filenames <- c('data/data_usa.csv', 'data/data_japan.csv',
'data/data_ukraine.csv', 'data/data_tajikistan.csv',
'data/data_mali.csv', 'data/data_haiti.csv')
country_names <- c("USA", "Japan", "Ukraine", "Tajikistan", "Mali", "Haiti")
features <- c("_____Mean_____", "_____Mode_____", "_____Median_____")
countries_matrix <- matrix(0, nrow=length(country_names), ncol=length(features),
dimnames=list(country_names, features))
# create general data frame for easier visualization
for (i in 1:length(filenames)) {
df <- read.csv(file = filenames[i])
df["country"] <- country_names[i]
correlated_df <- df[, c("life_expectancy", "health_expenditure",
"waged_workers", "gdp",
"employment_ratio", "expense",
"country")]
if (i == 1) {
general_df <- correlated_df
}
else {
general_df <- rbind(general_df,
correlated_df)
}
# clear a column from NaN values
filtered_list <- na.omit(correlated_df$life_expectancy)
countries_matrix[i, 1] = mean(filtered_list)
countries_matrix[i, 2] = get_mode(sapply(filtered_list, FUN=round))
countries_matrix[i, 3] = median(filtered_list)
}
write.csv(general_df, "data/general_df.csv", row.names=FALSE)
print(countries_matrix)
_____Mean_____ _____Mode_____ _____Median_____
USA 75.77099 75 75.62073
Japan 79.53053 83 79.61171
Ukraine 69.29167 68 69.22172
Tajikistan 61.69115 58 59.25900
Mali 46.77796 47 46.54650
Haiti 55.47958 56 55.67600
Boxplots for comparison of different features
Plotly library also gives you an opportunity to zoom in and
hover over the cursor on the boxplot and see the real numbers (>‿◠)✌
On the below plots we can see that in the majority of the countries Life expectancy really corresponds to our features. Our boxplots show Min, Q1, Median, Q3 and Max characteristics. In some cases, for ex. USA has the biggest Health expenditure, but it does not have the longest life expectacy (it was also found out in predictions of our linear regression for this feature and USA)
p <- ggplot(general_df, aes(country, life_expectancy)) +
ggtitle("Life expectancy of different countries") +
labs(y="Years") +
geom_boxplot(aes(color = country, fill = country), alpha=.5)
ggplotly(p)
Removed 7 rows containing non-finite values (stat_boxplot).
`
p <- ggplot(general_df, aes(country, health_expenditure)) +
ggtitle("Health expenditure of different countries") +
labs(y = "Health expenditure") +
geom_boxplot(aes(color = country, fill = country), alpha=.5)
ggplotly(p)
Removed 181 rows containing non-finite values (stat_boxplot).
p <- ggplot(general_df, aes(country, waged_workers)) +
ggtitle("Waged workers of different countries") +
labs(y = "% of population") +
geom_boxplot(aes(color = country, fill = country), alpha=.5)
ggplotly(p)
Removed 120 rows containing non-finite values (stat_boxplot).
p <- ggplot(general_df, aes(country, gdp)) +
ggtitle("GDP of different countries") +
labs(y = "GDP per capita") +
geom_boxplot(aes(color = country, fill = country), alpha=.5)
ggplotly(p)
Removed 36 rows containing non-finite values (stat_boxplot).
p <- ggplot(general_df, aes(country, expense)) +
ggtitle("Employment ratio of different countries") +
labs(y="% of population") +
geom_boxplot(aes(color = country, fill = country), alpha=.5)
ggplotly(p)
Removed 173 rows containing non-finite values (stat_boxplot).
p <- ggplot(general_df, aes(country, expense)) +
ggtitle("Expense of different countries") +
labs(y = "Expense") +
geom_boxplot(aes(color = country, fill = country), alpha=.5)
ggplotly(p)
Removed 173 rows containing non-finite values (stat_boxplot).
Plots for comparison of different densities
For clear understanding, if graph is closer to the right part,
so the feature for such country is bigger :=)
Also like previously, on the below plots we can see that in the majority of the countries Life expectancy really corresponds to our features. Now we explore the density of different features of the countries.
After its investigating we understand that countries with high level of economic development have passed a long way of improvement and make it with small steps, but periodically. On the other hand, countries with less level of development can stay with the same indicators of some features through the years.
p <- ggplot(general_df, aes(x = life_expectancy, fill = country))+
geom_density(adjust=1.5, alpha=.4) +
ggtitle("Life expectancy of different countries") +
labs(y="Density", x = "Life expectancy")
ggplotly(p)
Removed 7 rows containing non-finite values (stat_density).
p <- ggplot(general_df, aes(x = health_expenditure, fill = country))+
geom_density(adjust=1.5, alpha=.4) +
ggtitle("Health expenditure of different countries") +
labs(y="Density", x = "Health expenditure")
ggplotly(p)
Removed 181 rows containing non-finite values (stat_density).
p <- ggplot(general_df, aes(x = waged_workers, fill = country))+
geom_density(adjust=1.5, alpha=.4) +
ggtitle("Waged workers of different countries") +
labs(y="Density", x = "Waged workers")
ggplotly(p)
Removed 120 rows containing non-finite values (stat_density).
You can zoom in if you want to look closer at some plots
USA and Japan have the biggest values of this parameter.
p <- ggplot(general_df, aes(x = gdp, fill = country))+
geom_density(adjust=1.5, alpha=.4) +
ggtitle("GDP of different countries") +
labs(y="Density", x = "GDP per capita")
ggplotly(p)
Removed 36 rows containing non-finite values (stat_density).
You can zoom in in case you want to look closer at some plots
USA and Japan have the biggest values of this parameter.
p <- ggplot(general_df, aes(x = employment_ratio, fill = country))+
geom_density(adjust=1.5, alpha=.4) +
ggtitle("Employment ratio of different countries") +
labs(y="Density", x = "Employment ratio") +
scale_x_continuous(limits=c(-5, 65))
ggplotly(p)
Removed 101 rows containing non-finite values (stat_density).
Here we actually see that partly due to large amount of expense Ukraine has less life expectancy that USA or Japan :=)
p <- ggplot(general_df, aes(x = expense, fill = country))+
geom_density(adjust=1.5, alpha=.4) +
ggtitle("Expense of different countries") +
labs(y="Density", x = "Expense")
ggplotly(p)
Removed 173 rows containing non-finite values (stat_density).
Exploring if data of Life expectancy of Ukraine follow one of the standard distributions
After exploring the results of Kolmogorov-Smirnov test we can see that our data follow in the majority (we made experiments for it) normal distribution with mean = mean(country_df$life_expectancy) and sd = sd(country_df$life_expectancy). However, uniform distribution with min = min(country_df$life_expectancy) and max = max(country_df$life_expectancy) also is pretty close.
It was proved with below visualizations.
library(tolerance)
country_df <- read.csv(file = 'data/data_ukraine.csv')
filtered_list <- na.omit(country_df$life_expectancy)
len_list <- length(filtered_list)
compare_norm <- rnorm(len_list, mean=mean(filtered_list),
sd=sd(filtered_list))
compare_exp <- r2exp(len_list, shift=min(filtered_list))
compare_unif <- runif(len_list, min = min(filtered_list), max = max(filtered_list))
ks.test(filtered_list, compare_norm)
Two-sample Kolmogorov-Smirnov test
data: filtered_list and compare_norm
D = 0.10417, p-value = 0.9602
alternative hypothesis: two-sided
ks.test(filtered_list, compare_exp)
Two-sample Kolmogorov-Smirnov test
data: filtered_list and compare_exp
D = 0.60417, p-value = 1.745e-08
alternative hypothesis: two-sided
ks.test(filtered_list, compare_unif)
Two-sample Kolmogorov-Smirnov test
data: filtered_list and compare_unif
D = 0.16667, p-value = 0.5221
alternative hypothesis: two-sided
library(lattice)
library(latticeExtra)
vals <- data.frame(feature=filtered_list,
norm_distr=compare_norm)
ecdfplot(~ feature + norm_distr, data=vals, auto.key=list(space='right'))

vals <- data.frame(feature=filtered_list,
exp_distr=compare_exp)
ecdfplot(~ feature + exp_distr, data=vals, auto.key=list(space='right'))

vals <- data.frame(feature=filtered_list,
unif_distr=compare_unif)
ecdfplot(~ feature + unif_distr, data=vals, auto.key=list(space='right'))

Conclusion
So, what we can see is that for every country the importance of some features may differ, take for example Tech, this feature is very significant in “Tech-countries” such as Japan and, as we can see, there is some linear relation between Life Expectancy and Tech industry there, but not for other countries. The same we can say about Binding Coverage as in High-Income Countries this parameter is always almost the same, which doesn’t show any linear relation, but this does not mean that it is insignificant (at least not for countries, but for our model).
We have covered what parameters do not give us any possibility to estimate Life Expectancy, let’s talt about the parameters, that have shown us a good linear relation. These are:
- Waged Workers Ratio (0.77 goodness of fit on average)
- GDP (0.75 goodness of fit on average)
- Health Expenditure (0.72 goodness of fit on average)
- Employment Ratio + Expense (0.6 goodness of fit on average)
Of course, these estimations are not very accurate because of the lack of data, but at least we can see that there is some relation between these parameters and life expectancy and it’s clear as everything reduces to if country can provide its residents with work, medicine and good finance capital (which depends on job), then those people can cover all their need to live long and healthy life.
LS0tDQp0aXRsZTogIlJlc2VhcmNoIHByb2plY3QiDQphdXRob3I6ICJEZW55cyBIZXJhc3ltdWsgYW5kIFlhcm9zbGF2IE1vcm96ZXZ5Y2giDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQojIyBBaW0NCg0KQXQgdGhpcyBleHBlcmltZW50IHdlIHdhbnQgdG8gZGV0ZXJtaW5lICoqd2hhdCBwb2xpdGljYWwgYW5kIGVjb25vbWljIGZlYXR1cmVzKiogY2FuIGNvcnJlbGF0ZSB3aXRoICoqTGlmZSBFeHBlY3RhbmN5KiogaW4gZGlmZmVyZW50IGNvdW50cmllcyBhbmQgdG8gZGV0ZXJtaW5lIGhvdyBkZWVwbHkgY2FuIHRoZXkgY29ycmVsYXRlIHRvIG1ha2Ugc29tZSBhc3N1bXB0aW9ucy4gV2Ugd2lsbCBkbyB0aGlzIGV4cGVyaW1lbnQgd2l0aCBzZXZlcmFsIGZlYXR1cmVzIGFuZCBzZXZlcmFsIGNvdW50cmllcywgYW5kIGFmdGVyIHRoYXQgd2Ugd2lsbCBtYWtlIHNvbWUgYXNzdW1wdGlvbnMuDQoNCiMjIENob29zaW5nIHByb3BlciBmZWF0dXJlcw0KDQpEYXRhc2V0IHdhcyB0YWtlbiBmcm9tIGh0dHBzOi8vZGF0YWJhbmsud29ybGRiYW5rLm9yZy9zb3VyY2Uvd29ybGQtZGV2ZWxvcG1lbnQtaW5kaWNhdG9ycyMgDQoNCkFtb25nIDE0NDAgZmVhdHVyZXMgd2UgaGF2ZSBjaG9zZW4gb25seSA0MiB0aGF0IGNvdWxkIGNvcnJlbGF0ZSB3aXRoIGxpZmUgZXhwZWN0YW5jeSwgYnV0IGFmdGVyIGFuYWx5emluZyBnYWluZWQgZGF0YSwgd2UgaGFkIHRvIGdldCByaWQgb2YgYXBwcm94aW1hdGVseSAzMCBmZWF0dXJlcyBiZWNhdXNlIG9mIHRoZSBsYWNrIG9mIGRhdGEuIEhvd2V2ZXIsIHdlIHN0aWxsIGhhdmUgc29tZSBmZWF0dXJlcyBsZWZ0IHRoYXQgY291bGQgY29ycmVsYXRlIHdpdGggY2hvc2VuIHBhcmFtZXRlcjoNCg0KKipHRFAgKHBlciBjYXBpdGEpKiosICoqRXhwZW5zZSAoJSBvZiBHRFApKiosICoqVGVjaCBJbmR1c3RyeSBQcm9ncmVzcyoqLCAqKkVtcGxveW1lbnQgUmF0aW8qKiwgKipXYWdlZCBXb3JrZXJzIFJhdGlvKiosICoqSGVhbHRoIEV4cGVuZGl0dXJlKiogYW5kICoqQmluZGluZyBDb3ZlcmFnZSoqLg0KDQojIyBDaG9vc2luZyBjb3VudHJpZXMNCg0KRm9yIHRoaXMgZXhwZXJpbWVudCB3ZSBoYXZlIGRlY2lkZWQgdG8gY2hvb3NlIHRoZSBjb3VudHJpZXMgd2l0aCBoaWdoLWluY29tZSAoVVNBLCBKYXBhbiksIG1pZGRsZS1pbmNvbWUgKFVrcmFpbmUsIFRhamlraXN0YW4pIGFuZCBsb3ctaW5jb21lIChNYWxpLCBIYWl0aSkgdG8gdW5kZXJzdGFuZCBvbiB3aGF0IHBhcmFtZXRlcnMgZGVwZW5kcyBsaWZlIGV4cGVjdGFuY3kgaW4gY291bnRyaWVzIHdpdGggZGlmZmVyZW50IG1vbmV5IGNhcGl0YWwuDQoNCiMjIEFwcHJvYWNoDQoNCldlIHdpbGwgdXNlIHRoZSBsaW5lYXIgcmVncmVzc2lvbiB0byBzZWUgaWYgdGhlcmUgaXMgYSBsaW5lYXIgcmVsYXRpb24gYmV0d2VlbiB0aGUgcGFyYW1ldGVycyB3ZSBoYXZlIGNob3NlbiBhbmQgdXNlIHRoaXMga25vd2xlZGdlIHRvIGJlIGFibGUgdG8gZGVjaWRlIHdoYXQgcGFyYW1ldGVycyByZWFsbHkgYWZmZWN0IHRoZSBsaWZlIGV4cGVjdGFuY3kuIFVzaW5nIGxpbmVhciByZWdyZXNzaW9uIHdlIHdpbGwgZGV0ZXJtaW5lIHRoZSBzaWduaWZpY2FuY2UgbGV2ZWwgb2YgZXZlcnkgcGFyYW1ldGVyIChpdHMgcC12YWx1ZSksIHdoaWNoIHdpbGwgdGVsbHMgdXMgZWl0aGVyIHdlIHdpbGwgcmVqZWN0IG51bGwgaHlwb3RoZXNpcyBvciBuby4gQWxzbywgdGhlIFItc3F1YXJlZCB3aWxsIHNob3cgdXMgaG93IGdvb2Qgb3VyIG1vZGVsIGlzLiBJbiBvdGhlciB3b3JkcywgaG93IGdvb2QgdGhpcyBsaW5lYXIgcmVsYXRpb24gaXMuDQoNCiMjIEh5cG90aGVzaXMNCg0KU28sIHdlIHdpbGwgaGF2ZSB0d28gaHlwb3RoZXNpcycsICRIXzAkICh0aGVyZSBpcyBubyBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZXNlIHBhcmFtZXRlcnMpIGFuZCAkSF8xJCAodGhlcmUgaXMgYXQgbGVhc3Qgb25lIHBhcmFtZXRlciB0aGF0IGNvcnJlbGF0ZXMpLg0KDQokJA0KICBIXzAgOiBcYmV0YSA9IFxiZXRhXzBcICAgXDtcO1w7XDsgSF8xOiBcYmV0YSBcbmVxIFxiZXRhXzANCiQkDQoNCmBgYHtyfQ0KIyBmdW5jdGlvbiB0byBwcmludCBkYXRhIG9mIGV4cGVyaW1lbnQNCnByaW50X21vZGVsIDwtIGZ1bmN0aW9uKG1vZGVsLCBmZWF0dXJlcykgew0KICBjYXQoIkZlYXR1cmVzOlx0IiwgZmVhdHVyZXMsICJcblItc3F1YXJlZDpcdCIsIHN1bW1hcnkobW9kZWwpJHIuc3F1YXJlZCwNCiAgICAiXG5QLXZhbHVlczpcdCIsIHN1bW1hcnkobW9kZWwpJGNvZWZmaWNpZW50c1ssNF0pDQp9DQpgYGANCg0KIyMgRXhwZXJpbWVudGluZyBvbiBIaWdoLWxldmVsIGNvdW50cmllcyAoVVNBLCBKYXBhbikNCg0KV2Ugd2lsbCB0cnkgdG8gZmluZCBjb3JyZWxhdGlvbiAqKmxpZmUgZXhwZWN0YW5jeSoqIHVzaW5nIHRoZSBkYXRhIHNldCBiZWxsb3cuIEFmdGVyIHRoaXMsIHdlIHdpbGwgZGVjaWRlIHdoYXQgZmVhdHVyZXMgY2FuIGJlIGNob3NlbiB0byBkZXRlcm1pbmUgd2hhdCByZWFsbHkgZWZmZWN0cyB0aGlzIHBhcmFtZXRlciBvZiBoaWdoLWxldmVsIGNvdW50cmllcy4gKlNvbWUgb2YgdGhlIGRhdGEgaXMgbWlzc2VkLCBidXQgd2UgZG8gbm90IHRha2UgdGhlIGZpcnN0IGxpbmVzIGludG8gY29uc2lkZXJhdGlvbiBhcyB3ZSBoYXZlIDUwLWxpbmUgZGF0YSBzZXQsIHdoZXJlIGVhY2ggbGluZSBjb3JyZXNwb25kcyB0byBjZXJ0YWluIHllYXIuKg0KDQoNCiMjIyBVU0ENCg0KYGBge3J9DQojIHJlYWQgY3N2IGZpbGUNCnVzYSA8LSByZWFkLmNzdihmaWxlID0gJ2RhdGEvZGF0YV91c2EuY3N2JykNCmhlYWQodXNhLCAzKQ0KYGBgDQoNCiMjIyMgVGVzdGluZyBmZWF0dXJlcw0KDQpgYGB7cn0NCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gdGVjaCwgZGF0YT11c2EpDQpwcmludF9tb2RlbChtb2RlbCwgIlRlY2giKQ0KDQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IGVtcGxveW1lbnRfcmF0aW8gKyBleHBlbnNlLCBkYXRhPXVzYSkNCnByaW50X21vZGVsKG1vZGVsLCAiRW1wbG95bWVudCBSYXRpbyArIEV4cGVuc2UiKQ0KDQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IHdhZ2VkX3dvcmtlcnMsIGRhdGE9dXNhKQ0KcHJpbnRfbW9kZWwobW9kZWwsICJXYWdlZCBXb3JrZXJzIFJhdGlvIikNCg0KbW9kZWwgPC0gbG0oZm9ybXVsYT1saWZlX2V4cGVjdGFuY3kgfiBoZWFsdGhfZXhwZW5kaXR1cmUsIGRhdGE9dXNhKQ0KcHJpbnRfbW9kZWwobW9kZWwsICJIZWFsdGggRXhwZW5kaXR1cmUiKQ0KDQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IGdkcCwgZGF0YT11c2EpDQpwcmludF9tb2RlbChtb2RlbCwgIkdEUCBwZXIgQ2FwaXRhIikNCmBgYA0KDQojIyMgSmFwYW4NCg0KYGBge3J9DQojIHJlYWQgY3N2IGZpbGUNCmphcGFuIDwtIHJlYWQuY3N2KGZpbGUgPSAnZGF0YS9kYXRhX2phcGFuLmNzdicpDQpoZWFkKGphcGFuLCAzKQ0KYGBgDQoNCiMjIyMgVGVzdGluZyBmZWF0dXJlcw0KDQpgYGB7cn0NCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gdGVjaCwgZGF0YT1qYXBhbikNCnByaW50X21vZGVsKG1vZGVsLCAiVGVjaCIpDQoNCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gZW1wbG95bWVudF9yYXRpbyArIGV4cGVuc2UsIGRhdGE9amFwYW4pDQpwcmludF9tb2RlbChtb2RlbCwgIkVtcGxveW1lbnQgUmF0aW8gKyBFeHBlbnNlIikNCg0KbW9kZWwgPC0gbG0oZm9ybXVsYT1saWZlX2V4cGVjdGFuY3kgfiB3YWdlZF93b3JrZXJzLCBkYXRhPWphcGFuKQ0KcHJpbnRfbW9kZWwobW9kZWwsICJXYWdlZCBXb3JrZXJzIFJhdGlvIikNCg0KbW9kZWwgPC0gbG0oZm9ybXVsYT1saWZlX2V4cGVjdGFuY3kgfiBoZWFsdGhfZXhwZW5kaXR1cmUsIGRhdGE9amFwYW4pDQpwcmludF9tb2RlbChtb2RlbCwgIkhlYWx0aCBFeHBlbmRpdHVyZSIpDQoNCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gZ2RwLCBkYXRhPWphcGFuKQ0KcHJpbnRfbW9kZWwobW9kZWwsICJHRFAgcGVyIENhcGl0YSIpDQpgYGANCg0KIyMgRXhwZXJpbWVudGluZyBvbiBNaWQtbGV2ZWwgY291bnRyaWVzIChVa3JhaW5lLCBUYWppa2lzdGFuKQ0KDQpXZSB3aWxsIHRyeSB0byBmaW5kIGNvcnJlbGF0aW9uICoqbGlmZSBleHBlY3RhbmN5KiogdXNpbmcgdGhlIGRhdGEgc2V0IGJlbGxvdy4gQWZ0ZXIgdGhpcywgd2Ugd2lsbCBkZWNpZGUgd2hhdCBmZWF0dXJlcyBjYW4gYmUgY2hvc2VuIHRvIGRldGVybWluZSB3aGF0IHJlYWxseSBlZmZlY3RzIHRoaXMgcGFyYW1ldGVyIG9mIG1pZC1sZXZlbCBjb3VudHJpZXMuICpTb21lIG9mIHRoZSBkYXRhIGlzIG1pc3NlZCwgYnV0IHdlIGRvIG5vdCB0YWtlIHRoZSBmaXJzdCBsaW5lcyBpbnRvIGNvbnNpZGVyYXRpb24gYXMgd2UgaGF2ZSA1MC1saW5lIGRhdGEgc2V0LCB3aGVyZSBlYWNoIGxpbmUgY29ycmVzcG9uZHMgdG8gY2VydGFpbiB5ZWFyLioNCg0KIyMjIFVrcmFpbmUNCg0KYGBge3J9DQojIHJlYWQgY3N2IGZpbGUNCnVrcmFpbmUgPC0gcmVhZC5jc3YoZmlsZSA9ICdkYXRhL2RhdGFfdWtyYWluZS5jc3YnKQ0KaGVhZCh1a3JhaW5lLCAzKQ0KYGBgDQoNCiMjIyMgVGVzdGluZyBmZWF0dXJlcw0KDQpgYGB7cn0NCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gdGVjaCwgZGF0YT11a3JhaW5lKQ0KcHJpbnRfbW9kZWwobW9kZWwsICJUZWNoIikNCg0KbW9kZWwgPC0gbG0oZm9ybXVsYT1saWZlX2V4cGVjdGFuY3kgfiBiaW5kaW5nX2NvdmVyYWdlLCBkYXRhPXVrcmFpbmUpDQpwcmludF9tb2RlbChtb2RlbCwgIkJpbmRpbmcgQ292ZXJhZ2UiKQ0KDQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IGVtcGxveW1lbnRfcmF0aW8gKyBleHBlbnNlLCBkYXRhPXVrcmFpbmUpDQpwcmludF9tb2RlbChtb2RlbCwgIkVtcGxveW1lbnQgUmF0aW8gKyBFeHBlbnNlIikNCg0KbW9kZWwgPC0gbG0oZm9ybXVsYT1saWZlX2V4cGVjdGFuY3kgfiB3YWdlZF93b3JrZXJzLCBkYXRhPXVrcmFpbmUpDQpwcmludF9tb2RlbChtb2RlbCwgIldhZ2VkIFdvcmtlcnMgUmF0aW8iKQ0KDQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IGhlYWx0aF9leHBlbmRpdHVyZSwgZGF0YT11a3JhaW5lKQ0KcHJpbnRfbW9kZWwobW9kZWwsICJIZWFsdGggRXhwZW5kaXR1cmUiKQ0KDQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IGdkcCwgZGF0YT11a3JhaW5lKQ0KcHJpbnRfbW9kZWwobW9kZWwsICJHRFAgcGVyIENhcGl0YSIpDQpgYGANCg0KIyMjIFRhamlraXN0YW4NCg0KYGBge3J9DQojIHJlYWQgY3N2IGZpbGUNCnRhamlraXN0YW4gPC0gcmVhZC5jc3YoZmlsZSA9ICdkYXRhL2RhdGFfdGFqaWtpc3Rhbi5jc3YnKQ0KaGVhZCh0YWppa2lzdGFuLCAzKQ0KYGBgDQoNCiMjIyMgVGVzdGluZyBmZWF0dXJlcw0KDQpgYGB7cn0NCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gdGVjaCwgZGF0YT10YWppa2lzdGFuKQ0KcHJpbnRfbW9kZWwobW9kZWwsICJUZWNoIikNCg0KbW9kZWwgPC0gbG0oZm9ybXVsYT1saWZlX2V4cGVjdGFuY3kgfiBiaW5kaW5nX2NvdmVyYWdlLCBkYXRhPXRhamlraXN0YW4pDQpwcmludF9tb2RlbChtb2RlbCwgIkJpbmRpbmcgQ292ZXJhZ2UiKQ0KDQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IGVtcGxveW1lbnRfcmF0aW8gKyBleHBlbnNlLCBkYXRhPXRhamlraXN0YW4pDQpwcmludF9tb2RlbChtb2RlbCwgIkVtcGxveW1lbnQgUmF0aW8gKyBFeHBlbnNlIikNCg0KbW9kZWwgPC0gbG0oZm9ybXVsYT1saWZlX2V4cGVjdGFuY3kgfiB3YWdlZF93b3JrZXJzLCBkYXRhPXRhamlraXN0YW4pDQpwcmludF9tb2RlbChtb2RlbCwgIldhZ2VkIFdvcmtlcnMgUmF0aW8iKQ0KDQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IGhlYWx0aF9leHBlbmRpdHVyZSwgZGF0YT10YWppa2lzdGFuKQ0KcHJpbnRfbW9kZWwobW9kZWwsICJIZWFsdGggRXhwZW5kaXR1cmUiKQ0KDQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IGdkcCwgZGF0YT10YWppa2lzdGFuKQ0KcHJpbnRfbW9kZWwobW9kZWwsICJHRFAgcGVyIENhcGl0YSIpDQpgYGANCg0KIyMgRXhwZXJpbWVudGluZyBvbiBMb3ctbGV2ZWwgY291bnRyaWVzIChNYWxpLCBIYWl0aSkNCg0KV2Ugd2lsbCB0cnkgdG8gZmluZCBjb3JyZWxhdGlvbiAqKmxpZmUgZXhwZWN0YW5jeSoqIHVzaW5nIHRoZSBkYXRhIHNldCBiZWxsb3cuIEFmdGVyIHRoaXMsIHdlIHdpbGwgZGVjaWRlIHdoYXQgZmVhdHVyZXMgY2FuIGJlIGNob3NlbiB0byBkZXRlcm1pbmUgd2hhdCByZWFsbHkgZWZmZWN0cyB0aGlzIHBhcmFtZXRlciBvZiBsb3ctbGV2ZWwgY291bnRyaWVzLiAqU29tZSBvZiB0aGUgZGF0YSBpcyBtaXNzZWQsIGJ1dCB3ZSBkbyBub3QgdGFrZSB0aGUgZmlyc3QgbGluZXMgaW50byBjb25zaWRlcmF0aW9uIGFzIHdlIGhhdmUgNTAtbGluZSBkYXRhIHNldCwgd2hlcmUgZWFjaCBsaW5lIGNvcnJlc3BvbmRzIHRvIGNlcnRhaW4geWVhci4qDQoNCiMjIyBNYWxpDQoNCmBgYHtyfQ0KIyByZWFkIGNzdiBmaWxlDQptYWxpIDwtIHJlYWQuY3N2KGZpbGUgPSAnZGF0YS9kYXRhX21hbGkuY3N2JykNCmhlYWQobWFsaSwgMykNCmBgYA0KDQojIyMjIFRlc3RpbmcgZmVhdHVyZXMNCg0KYGBge3J9DQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IGJpbmRpbmdfY292ZXJhZ2UsIGRhdGE9bWFsaSkNCnByaW50X21vZGVsKG1vZGVsLCAiQmluZGluZyBDb3ZlcmFnZSIpDQoNCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gZW1wbG95bWVudF9yYXRpbyArIGV4cGVuc2UsIGRhdGE9bWFsaSkNCnByaW50X21vZGVsKG1vZGVsLCAiRW1wbG95bWVudCBSYXRpbyArIEV4cGVuc2UiKQ0KDQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IHdhZ2VkX3dvcmtlcnMsIGRhdGE9bWFsaSkNCnByaW50X21vZGVsKG1vZGVsLCAiV2FnZWQgV29ya2VycyBSYXRpbyIpDQoNCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gaGVhbHRoX2V4cGVuZGl0dXJlLCBkYXRhPW1hbGkpDQpwcmludF9tb2RlbChtb2RlbCwgIkhlYWx0aCBFeHBlbmRpdHVyZSIpDQoNCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gZ2RwLCBkYXRhPW1hbGkpDQpwcmludF9tb2RlbChtb2RlbCwgIkdEUCBwZXIgQ2FwaXRhIikNCmBgYA0KDQojIyMgSGFpdGkNCg0KYGBge3J9DQojIHJlYWQgY3N2IGZpbGUNCmhhaXRpIDwtIHJlYWQuY3N2KGZpbGUgPSAnZGF0YS9kYXRhX2hhaXRpLmNzdicpDQpoZWFkKGhhaXRpLCAzKQ0KYGBgDQoNCiMjIyMgVGVzdGluZyBmZWF0dXJlcw0KDQpgYGB7cn0NCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gdGVjaCwgZGF0YT1oYWl0aSkNCnByaW50X21vZGVsKG1vZGVsLCAiVGVjaCIpDQoNCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gYmluZGluZ19jb3ZlcmFnZSwgZGF0YT1oYWl0aSkNCnByaW50X21vZGVsKG1vZGVsLCAiQmluZGluZyBDb3ZlcmFnZSIpDQoNCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gZW1wbG95bWVudF9yYXRpbywgZGF0YT1oYWl0aSkNCnByaW50X21vZGVsKG1vZGVsLCAiRW1wbG95bWVudCBSYXRpbyIpDQoNCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gd2FnZWRfd29ya2VycywgZGF0YT1oYWl0aSkNCnByaW50X21vZGVsKG1vZGVsLCAiV2FnZWQgV29ya2VycyBSYXRpbyIpDQoNCm1vZGVsIDwtIGxtKGZvcm11bGE9bGlmZV9leHBlY3RhbmN5IH4gaGVhbHRoX2V4cGVuZGl0dXJlLCBkYXRhPWhhaXRpKQ0KcHJpbnRfbW9kZWwobW9kZWwsICJIZWFsdGggRXhwZW5kaXR1cmUiKQ0KDQptb2RlbCA8LSBsbShmb3JtdWxhPWxpZmVfZXhwZWN0YW5jeSB+IGdkcCwgZGF0YT1oYWl0aSkNCnByaW50X21vZGVsKG1vZGVsLCAiR0RQIHBlciBDYXBpdGEiKQ0KYGBgDQoNCiMgVmlzdWFsaXphdGlvbiBwYXJ0DQoNCkluIHRoZSBhYm92ZSBwYXJ0LCB3ZSBoYXZlIHVuZGVyc3Rvb2QgdGhhdCAqKkxpZmUgZXhwZWN0YW5jeSoqIGlzIHRoZSBtb3N0IGxpbmVhcmx5IGRlcGVuZGVudCBvbiBzdWNoIGZlYXR1cmVzIGFzICoqSGVhbHRoIGV4cGVuZGl0dXJlKiosICoqV2FnZWQgd29ya2VycyoqLCAgKipHRFAgcGVyIGNhcGl0YSoqLCAqKkVtcGxveW1lbnQgcmF0aW8qKiBhbmQgKipFeHBlbnNlKiouIEl0IHdhcyBmb3VuZCBvdXQgYmFzZWQgb24gdGhlIHJlc3VsdHMgb2YgdGhlIG1ham9yaXR5IG9mIGNvdW50cmllcywgd2hlcmUgdGhleSBhcmUgZGVwZW5kZW50LiANCg0KTm93ICoqdGhlIG1haW4gYWltIG9mIHZpc3VhbGl6YXRpb24gcGFydCoqIGlzIHRvIHJlYWxseSBzZWUsIGNvbXBhcmUgdGhlIHJlc3VsdHMgd2l0aCBncmFwaHMsIGtub3cgaW50ZXJlc3RpbmcgZmFjdHMgYWJvdXQgb3VyIGFuZCBvdGhlciBjb3VudHJpZXMgYW5kIG1ha2Ugc3VyZSBvZiB0aGUgdHJ1dGggb2YgdGhlIGZpbmRpbmdzLg0KDQoNCg0KYGBge3J9DQpyZXF1aXJlKGdncGxvdDIpDQpsaWJyYXJ5KGdncGxvdDIpDQoNCmxpYnJhcnkocGxvdGx5KQ0KDQpsaWJyYXJ5KGRnb2YpIA0KbGlicmFyeSgncGxvdC5tYXRyaXgnKQ0KDQpgYGANCg0KDQojIyBNYXRyaXggZm9yIHRlbmRlbmN5IG9mIE1lYW4sIE1vZGUsIE1lYWRpYW4gb2YgbGlmZSBleHBlY3RhbmN5IG9mIHRoZSBjb3VudHJpZXMNCg0KIyMjIyBEYXRhIGhhdmUgYmVlbiBjb2xsZWN0ZWQgdGhyb3VnaCAzMC01MCB5ZWFycw0KDQoNCkFjY29yZGluZyB0byB0aGlzIG1hdHJpeCB3ZSBjYW4gc2VlIGdlbmVyYWwgdGVuZGVuY3kgb2YgbGlmZSBleHBlY3RhbmN5IG9mIHRoZSBjb3VudHJpZXMgYW5kIHBsYWNlIHRoZW0gYnkgdmFsdWUgb2YgdGhpcyBpbmRpY2F0b3Ioc3RhcnRpbmcgZnJvbSBsb25nZXN0KToNCkphcGFuLCBVU0EsIFVrcmFpbmUsIFRhamlraXN0YW4sIEhhaXRpLCBNYWxpDQoNCmBgYHtyfQ0KDQoNCmdldF9tb2RlIDwtIGZ1bmN0aW9uKHYpIHsNCiAgIHVuaXF2IDwtIHVuaXF1ZSh2KQ0KICAgdW5pcXZbd2hpY2gubWF4KHRhYnVsYXRlKG1hdGNoKHYsIHVuaXF2KSkpXQ0KfQ0KDQoNCmZpbGVuYW1lcyA8LSBjKCdkYXRhL2RhdGFfdXNhLmNzdicsICdkYXRhL2RhdGFfamFwYW4uY3N2JywNCiAgICAgICAgICAgICAgICdkYXRhL2RhdGFfdWtyYWluZS5jc3YnLCAnZGF0YS9kYXRhX3RhamlraXN0YW4uY3N2JywNCiAgICAgICAgICAgICAgICdkYXRhL2RhdGFfbWFsaS5jc3YnLCAnZGF0YS9kYXRhX2hhaXRpLmNzdicpDQoNCmNvdW50cnlfbmFtZXMgPC0gYygiVVNBIiwgIkphcGFuIiwgIlVrcmFpbmUiLCAiVGFqaWtpc3RhbiIsICJNYWxpIiwgIkhhaXRpIikNCmZlYXR1cmVzIDwtIGMoIl9fX19fTWVhbl9fX19fIiwgIl9fX19fTW9kZV9fX19fIiwgIl9fX19fTWVkaWFuX19fX18iKQ0KDQpjb3VudHJpZXNfbWF0cml4IDwtIG1hdHJpeCgwLCBucm93PWxlbmd0aChjb3VudHJ5X25hbWVzKSwgbmNvbD1sZW5ndGgoZmVhdHVyZXMpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1uYW1lcz1saXN0KGNvdW50cnlfbmFtZXMsIGZlYXR1cmVzKSkNCg0KIyBjcmVhdGUgZ2VuZXJhbCBkYXRhIGZyYW1lIGZvciBlYXNpZXIgdmlzdWFsaXphdGlvbg0KZm9yIChpIGluIDE6bGVuZ3RoKGZpbGVuYW1lcykpIHsNCiAgZGYgPC0gcmVhZC5jc3YoZmlsZSA9IGZpbGVuYW1lc1tpXSkNCiAgZGZbImNvdW50cnkiXSA8LSBjb3VudHJ5X25hbWVzW2ldDQogIA0KICBjb3JyZWxhdGVkX2RmIDwtIGRmWywgYygibGlmZV9leHBlY3RhbmN5IiwgImhlYWx0aF9leHBlbmRpdHVyZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJ3YWdlZF93b3JrZXJzIiwgICJnZHAiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiZW1wbG95bWVudF9yYXRpbyIsICJleHBlbnNlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgImNvdW50cnkiKV0NCiAgDQogIGlmIChpID09IDEpIHsNCiAgICBnZW5lcmFsX2RmIDwtIGNvcnJlbGF0ZWRfZGYNCiAgfQ0KICBlbHNlIHsNCiAgICBnZW5lcmFsX2RmIDwtIHJiaW5kKGdlbmVyYWxfZGYsIA0KICAgICAgICAgICAgICAgICAgICAgICAgY29ycmVsYXRlZF9kZikgDQogIH0NCiAgDQogICMgY2xlYXIgYSBjb2x1bW4gZnJvbSBOYU4gdmFsdWVzDQogIGZpbHRlcmVkX2xpc3QgPC0gbmEub21pdChjb3JyZWxhdGVkX2RmJGxpZmVfZXhwZWN0YW5jeSkNCiAgDQogIGNvdW50cmllc19tYXRyaXhbaSwgMV0gPSBtZWFuKGZpbHRlcmVkX2xpc3QpDQogIGNvdW50cmllc19tYXRyaXhbaSwgMl0gPSBnZXRfbW9kZShzYXBwbHkoZmlsdGVyZWRfbGlzdCwgRlVOPXJvdW5kKSkNCiAgY291bnRyaWVzX21hdHJpeFtpLCAzXSA9IG1lZGlhbihmaWx0ZXJlZF9saXN0KQ0KfQ0KDQp3cml0ZS5jc3YoZ2VuZXJhbF9kZiwgImRhdGEvZ2VuZXJhbF9kZi5jc3YiLCByb3cubmFtZXM9RkFMU0UpDQoNCnByaW50KGNvdW50cmllc19tYXRyaXgpDQoNCmBgYA0KDQojIyBCb3hwbG90cyBmb3IgY29tcGFyaXNvbiBvZiBkaWZmZXJlbnQgZmVhdHVyZXMNCg0KIyMjIyBQbG90bHkgbGlicmFyeSBhbHNvIGdpdmVzIHlvdSBhbiBvcHBvcnR1bml0eSB0byB6b29tIGluIGFuZA0KIyMjIyBob3ZlciBvdmVyIHRoZSBjdXJzb3Igb24gdGhlIGJveHBsb3QgYW5kIHNlZSB0aGUgcmVhbCBudW1iZXJzICAoPuKAv+KXoCninIwNCg0KDQpPbiB0aGUgYmVsb3cgcGxvdHMgd2UgY2FuIHNlZSB0aGF0ICoqaW4gdGhlIG1ham9yaXR5IG9mIHRoZSBjb3VudHJpZXMqKiBMaWZlIGV4cGVjdGFuY3kgKipyZWFsbHkgY29ycmVzcG9uZHMqKiB0byBvdXIgZmVhdHVyZXMuIE91ciBib3hwbG90cyBzaG93IE1pbiwgUTEsIE1lZGlhbiwgUTMgYW5kIE1heCBjaGFyYWN0ZXJpc3RpY3MuDQpJbiBzb21lIGNhc2VzLCBmb3IgZXguIFVTQSBoYXMgdGhlIGJpZ2dlc3QgSGVhbHRoIGV4cGVuZGl0dXJlLCBidXQgaXQgZG9lcyBub3QgaGF2ZSB0aGUgbG9uZ2VzdCBsaWZlIGV4cGVjdGFjeSAoaXQgd2FzIGFsc28gZm91bmQgb3V0IGluIHByZWRpY3Rpb25zIG9mIG91ciBsaW5lYXIgcmVncmVzc2lvbiBmb3IgdGhpcyBmZWF0dXJlIGFuZCBVU0EpDQoNCg0KYGBge3J9DQpwIDwtIGdncGxvdChnZW5lcmFsX2RmLCBhZXMoY291bnRyeSwgbGlmZV9leHBlY3RhbmN5KSkgKw0KICBnZ3RpdGxlKCJMaWZlIGV4cGVjdGFuY3kgb2YgZGlmZmVyZW50IGNvdW50cmllcyIpICsNCiAgbGFicyh5PSJZZWFycyIpICsNCiAgZ2VvbV9ib3hwbG90KGFlcyhjb2xvciA9IGNvdW50cnksIGZpbGwgPSBjb3VudHJ5KSwgYWxwaGE9LjUpDQoNCmdncGxvdGx5KHApDQoNCmBgYA0KYA0KYGBge3J9DQpwIDwtIGdncGxvdChnZW5lcmFsX2RmLCBhZXMoY291bnRyeSwgaGVhbHRoX2V4cGVuZGl0dXJlKSkgKw0KICBnZ3RpdGxlKCJIZWFsdGggZXhwZW5kaXR1cmUgb2YgZGlmZmVyZW50IGNvdW50cmllcyIpICsNCiAgbGFicyh5ID0gIkhlYWx0aCBleHBlbmRpdHVyZSIpICsNCiAgZ2VvbV9ib3hwbG90KGFlcyhjb2xvciA9IGNvdW50cnksIGZpbGwgPSBjb3VudHJ5KSwgYWxwaGE9LjUpDQoNCmdncGxvdGx5KHApDQoNCmBgYA0KDQoNCmBgYHtyfQ0KcCA8LSBnZ3Bsb3QoZ2VuZXJhbF9kZiwgYWVzKGNvdW50cnksIHdhZ2VkX3dvcmtlcnMpKSArDQogIGdndGl0bGUoIldhZ2VkIHdvcmtlcnMgb2YgZGlmZmVyZW50IGNvdW50cmllcyIpICsNCiAgbGFicyh5ID0gIiUgb2YgcG9wdWxhdGlvbiIpICsNCiAgZ2VvbV9ib3hwbG90KGFlcyhjb2xvciA9IGNvdW50cnksIGZpbGwgPSBjb3VudHJ5KSwgYWxwaGE9LjUpDQoNCmdncGxvdGx5KHApDQoNCmBgYA0KDQoNCmBgYHtyfQ0KcCA8LSBnZ3Bsb3QoZ2VuZXJhbF9kZiwgYWVzKGNvdW50cnksIGdkcCkpICsNCiAgZ2d0aXRsZSgiR0RQIG9mIGRpZmZlcmVudCBjb3VudHJpZXMiKSArDQogIGxhYnMoeSA9ICJHRFAgcGVyIGNhcGl0YSIpICsNCiAgZ2VvbV9ib3hwbG90KGFlcyhjb2xvciA9IGNvdW50cnksIGZpbGwgPSBjb3VudHJ5KSwgYWxwaGE9LjUpDQoNCmdncGxvdGx5KHApDQoNCmBgYA0KDQoNCmBgYHtyfQ0KcCA8LSBnZ3Bsb3QoZ2VuZXJhbF9kZiwgYWVzKGNvdW50cnksIGV4cGVuc2UpKSArDQogIGdndGl0bGUoIkVtcGxveW1lbnQgcmF0aW8gb2YgZGlmZmVyZW50IGNvdW50cmllcyIpICsNCiAgbGFicyh5PSIlIG9mIHBvcHVsYXRpb24iKSArDQogIGdlb21fYm94cGxvdChhZXMoY29sb3IgPSBjb3VudHJ5LCBmaWxsID0gY291bnRyeSksIGFscGhhPS41KQ0KDQpnZ3Bsb3RseShwKQ0KDQpgYGANCmBgYHtyfQ0KcCA8LSBnZ3Bsb3QoZ2VuZXJhbF9kZiwgYWVzKGNvdW50cnksIGV4cGVuc2UpKSArDQogIGdndGl0bGUoIkV4cGVuc2Ugb2YgZGlmZmVyZW50IGNvdW50cmllcyIpICsNCiAgbGFicyh5ID0gIkV4cGVuc2UiKSArDQogIGdlb21fYm94cGxvdChhZXMoY29sb3IgPSBjb3VudHJ5LCBmaWxsID0gY291bnRyeSksIGFscGhhPS41KQ0KDQpnZ3Bsb3RseShwKQ0KDQpgYGANCg0KDQojIyBQbG90cyBmb3IgY29tcGFyaXNvbiBvZiBkaWZmZXJlbnQgZGVuc2l0aWVzDQoNCiMjIyMgRm9yIGNsZWFyIHVuZGVyc3RhbmRpbmcsIGlmIGdyYXBoIGlzIGNsb3NlciB0byB0aGUgcmlnaHQgcGFydCwNCiMjIyMgc28gdGhlIGZlYXR1cmUgZm9yIHN1Y2ggY291bnRyeSBpcyBiaWdnZXIgOj0pDQoNCg0KQWxzbyBsaWtlIHByZXZpb3VzbHksIG9uIHRoZSBiZWxvdyBwbG90cyB3ZSBjYW4gc2VlIHRoYXQgKippbiB0aGUgbWFqb3JpdHkgb2YgdGhlIGNvdW50cmllcyoqIExpZmUgZXhwZWN0YW5jeSAqKnJlYWxseSBjb3JyZXNwb25kcyoqIHRvIG91ciBmZWF0dXJlcy4gTm93IHdlIGV4cGxvcmUgdGhlIGRlbnNpdHkgb2YgZGlmZmVyZW50IGZlYXR1cmVzIG9mIHRoZSBjb3VudHJpZXMuDQoNCkFmdGVyIGl0cyBpbnZlc3RpZ2F0aW5nIHdlIHVuZGVyc3RhbmQgdGhhdCBjb3VudHJpZXMgd2l0aCBoaWdoIGxldmVsIG9mIGVjb25vbWljIGRldmVsb3BtZW50IGhhdmUgcGFzc2VkIGEgbG9uZyB3YXkgb2YgaW1wcm92ZW1lbnQgYW5kIG1ha2UgaXQgd2l0aCBzbWFsbCBzdGVwcywgYnV0IHBlcmlvZGljYWxseS4gT24gdGhlIG90aGVyIGhhbmQsIGNvdW50cmllcyB3aXRoIGxlc3MgbGV2ZWwgb2YgZGV2ZWxvcG1lbnQgY2FuIHN0YXkgd2l0aCB0aGUgc2FtZSBpbmRpY2F0b3JzIG9mIHNvbWUgZmVhdHVyZXMgdGhyb3VnaCB0aGUgeWVhcnMuDQoNCg0KYGBge3J9DQpwIDwtIGdncGxvdChnZW5lcmFsX2RmLCBhZXMoeCA9IGxpZmVfZXhwZWN0YW5jeSwgZmlsbCA9IGNvdW50cnkpKSsNCiAgZ2VvbV9kZW5zaXR5KGFkanVzdD0xLjUsIGFscGhhPS40KSArIA0KICBnZ3RpdGxlKCJMaWZlIGV4cGVjdGFuY3kgb2YgZGlmZmVyZW50IGNvdW50cmllcyIpICsNCiAgbGFicyh5PSJEZW5zaXR5IiwgeCA9ICJMaWZlIGV4cGVjdGFuY3kiKQ0KDQpnZ3Bsb3RseShwKQ0KDQpgYGANCg0KYGBge3J9DQpwIDwtIGdncGxvdChnZW5lcmFsX2RmLCBhZXMoeCA9IGhlYWx0aF9leHBlbmRpdHVyZSwgZmlsbCA9IGNvdW50cnkpKSsNCiAgZ2VvbV9kZW5zaXR5KGFkanVzdD0xLjUsIGFscGhhPS40KSArIA0KICBnZ3RpdGxlKCJIZWFsdGggZXhwZW5kaXR1cmUgb2YgZGlmZmVyZW50IGNvdW50cmllcyIpICsNCiAgbGFicyh5PSJEZW5zaXR5IiwgeCA9ICJIZWFsdGggZXhwZW5kaXR1cmUiKQ0KDQpnZ3Bsb3RseShwKQ0KDQpgYGANCg0KDQpgYGB7cn0NCnAgPC0gZ2dwbG90KGdlbmVyYWxfZGYsIGFlcyh4ID0gd2FnZWRfd29ya2VycywgZmlsbCA9IGNvdW50cnkpKSsNCiAgZ2VvbV9kZW5zaXR5KGFkanVzdD0xLjUsIGFscGhhPS40KSArIA0KICBnZ3RpdGxlKCJXYWdlZCB3b3JrZXJzIG9mIGRpZmZlcmVudCBjb3VudHJpZXMiKSArDQogIGxhYnMoeT0iRGVuc2l0eSIsIHggPSAiV2FnZWQgd29ya2VycyIpDQoNCmdncGxvdGx5KHApDQoNCmBgYA0KDQoNCiMjIyMgWW91IGNhbiB6b29tIGluIGlmIHlvdSB3YW50IHRvIGxvb2sgY2xvc2VyIGF0IHNvbWUgcGxvdHMNCg0KVVNBIGFuZCBKYXBhbiBoYXZlIHRoZSBiaWdnZXN0IHZhbHVlcyBvZiB0aGlzIHBhcmFtZXRlci4NCg0KYGBge3J9DQpwIDwtIGdncGxvdChnZW5lcmFsX2RmLCBhZXMoeCA9IGdkcCwgZmlsbCA9IGNvdW50cnkpKSsNCiAgZ2VvbV9kZW5zaXR5KGFkanVzdD0xLjUsIGFscGhhPS40KSArIA0KICBnZ3RpdGxlKCJHRFAgb2YgZGlmZmVyZW50IGNvdW50cmllcyIpICsNCiAgbGFicyh5PSJEZW5zaXR5IiwgeCA9ICJHRFAgcGVyIGNhcGl0YSIpDQoNCmdncGxvdGx5KHApDQoNCmBgYA0KDQoNCiMjIyMgWW91IGNhbiB6b29tIGluIGluIGNhc2UgeW91IHdhbnQgdG8gbG9vayBjbG9zZXIgYXQgc29tZSBwbG90cw0KDQoNClVTQSBhbmQgSmFwYW4gaGF2ZSB0aGUgYmlnZ2VzdCB2YWx1ZXMgb2YgdGhpcyBwYXJhbWV0ZXIuDQoNCg0KYGBge3J9DQpwIDwtIGdncGxvdChnZW5lcmFsX2RmLCBhZXMoeCA9IGVtcGxveW1lbnRfcmF0aW8sIGZpbGwgPSBjb3VudHJ5KSkrDQogIGdlb21fZGVuc2l0eShhZGp1c3Q9MS41LCBhbHBoYT0uNCkgKyANCiAgZ2d0aXRsZSgiRW1wbG95bWVudCByYXRpbyBvZiBkaWZmZXJlbnQgY291bnRyaWVzIikgKw0KICBsYWJzKHk9IkRlbnNpdHkiLCB4ID0gIkVtcGxveW1lbnQgcmF0aW8iKSArDQogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygtNSwgNjUpKQ0KDQpnZ3Bsb3RseShwKQ0KDQpgYGANCg0KDQpIZXJlIHdlIGFjdHVhbGx5IHNlZSB0aGF0IHBhcnRseSBkdWUgdG8gbGFyZ2UgYW1vdW50IG9mIGV4cGVuc2UgVWtyYWluZSBoYXMgbGVzcyBsaWZlIGV4cGVjdGFuY3kgdGhhdCBVU0Egb3IgSmFwYW4gOj0pDQoNCmBgYHtyfQ0KcCA8LSBnZ3Bsb3QoZ2VuZXJhbF9kZiwgYWVzKHggPSBleHBlbnNlLCBmaWxsID0gY291bnRyeSkpKw0KICBnZW9tX2RlbnNpdHkoYWRqdXN0PTEuNSwgYWxwaGE9LjQpICsgDQogIGdndGl0bGUoIkV4cGVuc2Ugb2YgZGlmZmVyZW50IGNvdW50cmllcyIpICsNCiAgbGFicyh5PSJEZW5zaXR5IiwgeCA9ICJFeHBlbnNlIikNCg0KZ2dwbG90bHkocCkNCg0KYGBgDQoNCg0KDQoNCg0KIyMgRXhwbG9yaW5nIGlmIGRhdGEgb2YgTGlmZSBleHBlY3RhbmN5IG9mIFVrcmFpbmUgZm9sbG93IG9uZSBvZiB0aGUgc3RhbmRhcmQgZGlzdHJpYnV0aW9ucw0KDQoNCkFmdGVyIGV4cGxvcmluZyB0aGUgcmVzdWx0cyBvZiBLb2xtb2dvcm92LVNtaXJub3YgdGVzdCB3ZSBjYW4gc2VlIHRoYXQgb3VyIGRhdGEgZm9sbG93IGluIHRoZSBtYWpvcml0eSAod2UgbWFkZSBleHBlcmltZW50cyBmb3IgaXQpICoqbm9ybWFsIGRpc3RyaWJ1dGlvbioqIHdpdGggbWVhbiA9IG1lYW4oY291bnRyeV9kZlwkbGlmZV9leHBlY3RhbmN5KSBhbmQgc2QgPSBzZChjb3VudHJ5X2RmXCRsaWZlX2V4cGVjdGFuY3kpLiBIb3dldmVyLCB1bmlmb3JtIGRpc3RyaWJ1dGlvbiB3aXRoIG1pbiA9IG1pbihjb3VudHJ5X2RmXCRsaWZlX2V4cGVjdGFuY3kpIGFuZCBtYXggPSBtYXgoY291bnRyeV9kZlwkbGlmZV9leHBlY3RhbmN5KSBhbHNvIGlzIHByZXR0eSBjbG9zZS4NCg0KSXQgd2FzIHByb3ZlZCB3aXRoIGJlbG93IHZpc3VhbGl6YXRpb25zLg0KDQoNCmBgYHtyfQ0KbGlicmFyeSh0b2xlcmFuY2UpDQpjb3VudHJ5X2RmIDwtIHJlYWQuY3N2KGZpbGUgPSAnZGF0YS9kYXRhX3VrcmFpbmUuY3N2JykNCg0KZmlsdGVyZWRfbGlzdCA8LSBuYS5vbWl0KGNvdW50cnlfZGYkbGlmZV9leHBlY3RhbmN5KQ0KDQpsZW5fbGlzdCA8LSBsZW5ndGgoZmlsdGVyZWRfbGlzdCkNCg0KY29tcGFyZV9ub3JtIDwtIHJub3JtKGxlbl9saXN0LCBtZWFuPW1lYW4oZmlsdGVyZWRfbGlzdCksIA0KICAgICAgICAgICAgICAgICAgICAgIHNkPXNkKGZpbHRlcmVkX2xpc3QpKQ0KY29tcGFyZV9leHAgPC0gcjJleHAobGVuX2xpc3QsIHNoaWZ0PW1pbihmaWx0ZXJlZF9saXN0KSkNCmNvbXBhcmVfdW5pZiA8LSBydW5pZihsZW5fbGlzdCwgbWluID0gbWluKGZpbHRlcmVkX2xpc3QpLCBtYXggPSBtYXgoZmlsdGVyZWRfbGlzdCkpDQoNCmtzLnRlc3QoZmlsdGVyZWRfbGlzdCwgY29tcGFyZV9ub3JtKQ0Ka3MudGVzdChmaWx0ZXJlZF9saXN0LCBjb21wYXJlX2V4cCkNCmtzLnRlc3QoZmlsdGVyZWRfbGlzdCwgY29tcGFyZV91bmlmKQ0KDQpgYGANCmBgYHtyfQ0KbGlicmFyeShsYXR0aWNlKQ0KbGlicmFyeShsYXR0aWNlRXh0cmEpDQoNCnZhbHMgPC0gZGF0YS5mcmFtZShmZWF0dXJlPWZpbHRlcmVkX2xpc3QsDQogICAgICAgICAgICAgICAgICAgbm9ybV9kaXN0cj1jb21wYXJlX25vcm0pDQoNCmVjZGZwbG90KH4gZmVhdHVyZSArIG5vcm1fZGlzdHIsIGRhdGE9dmFscywgYXV0by5rZXk9bGlzdChzcGFjZT0ncmlnaHQnKSkNCg0KYGBgDQpgYGB7cn0NCnZhbHMgPC0gZGF0YS5mcmFtZShmZWF0dXJlPWZpbHRlcmVkX2xpc3QsDQogICAgICAgICAgICAgICAgICAgZXhwX2Rpc3RyPWNvbXBhcmVfZXhwKQ0KDQplY2RmcGxvdCh+IGZlYXR1cmUgKyBleHBfZGlzdHIsIGRhdGE9dmFscywgYXV0by5rZXk9bGlzdChzcGFjZT0ncmlnaHQnKSkNCg0KYGBgDQpgYGB7cn0NCnZhbHMgPC0gZGF0YS5mcmFtZShmZWF0dXJlPWZpbHRlcmVkX2xpc3QsDQogICAgICAgICAgICAgICAgICAgdW5pZl9kaXN0cj1jb21wYXJlX3VuaWYpDQoNCmVjZGZwbG90KH4gZmVhdHVyZSArIHVuaWZfZGlzdHIsIGRhdGE9dmFscywgYXV0by5rZXk9bGlzdChzcGFjZT0ncmlnaHQnKSkNCg0KYGBgDQoNCiMgQ29uY2x1c2lvbg0KDQpTbywgd2hhdCB3ZSBjYW4gc2VlIGlzIHRoYXQgZm9yIGV2ZXJ5IGNvdW50cnkgdGhlIGltcG9ydGFuY2Ugb2Ygc29tZSBmZWF0dXJlcyBtYXkgZGlmZmVyLCB0YWtlIGZvciBleGFtcGxlICoqVGVjaCoqLCB0aGlzIGZlYXR1cmUgaXMgdmVyeSBzaWduaWZpY2FudCBpbiAiVGVjaC1jb3VudHJpZXMiIHN1Y2ggYXMgSmFwYW4gYW5kLCBhcyB3ZSBjYW4gc2VlLCB0aGVyZSBpcyBzb21lIGxpbmVhciByZWxhdGlvbiBiZXR3ZWVuIExpZmUgRXhwZWN0YW5jeSBhbmQgVGVjaCBpbmR1c3RyeSB0aGVyZSwgYnV0IG5vdCBmb3Igb3RoZXIgY291bnRyaWVzLiBUaGUgc2FtZSB3ZSBjYW4gc2F5IGFib3V0ICoqQmluZGluZyBDb3ZlcmFnZSoqIGFzIGluIEhpZ2gtSW5jb21lIENvdW50cmllcyB0aGlzIHBhcmFtZXRlciBpcyBhbHdheXMgYWxtb3N0IHRoZSBzYW1lLCB3aGljaCBkb2Vzbid0IHNob3cgYW55IGxpbmVhciByZWxhdGlvbiwgYnV0IHRoaXMgZG9lcyBub3QgbWVhbiB0aGF0IGl0IGlzIGluc2lnbmlmaWNhbnQgKGF0IGxlYXN0IG5vdCBmb3IgY291bnRyaWVzLCBidXQgZm9yIG91ciBtb2RlbCkuDQoNCldlIGhhdmUgY292ZXJlZCB3aGF0IHBhcmFtZXRlcnMgZG8gbm90IGdpdmUgdXMgYW55IHBvc3NpYmlsaXR5IHRvIGVzdGltYXRlIExpZmUgRXhwZWN0YW5jeSwgbGV0J3MgdGFsdCBhYm91dCB0aGUgcGFyYW1ldGVycywgdGhhdCBoYXZlIHNob3duIHVzIGEgZ29vZCBsaW5lYXIgcmVsYXRpb24uIFRoZXNlIGFyZToNCg0KMS4gKipXYWdlZCBXb3JrZXJzIFJhdGlvKiogKDAuNzcgZ29vZG5lc3Mgb2YgZml0IG9uIGF2ZXJhZ2UpDQoyLiAqKkdEUCoqICgwLjc1IGdvb2RuZXNzIG9mIGZpdCBvbiBhdmVyYWdlKQ0KMy4gKipIZWFsdGggRXhwZW5kaXR1cmUqKiAoMC43MiBnb29kbmVzcyBvZiBmaXQgb24gYXZlcmFnZSkNCjQuICoqRW1wbG95bWVudCBSYXRpbyArIEV4cGVuc2UqKiAoMC42IGdvb2RuZXNzIG9mIGZpdCBvbiBhdmVyYWdlKQ0KDQpPZiBjb3Vyc2UsIHRoZXNlIGVzdGltYXRpb25zIGFyZSBub3QgdmVyeSBhY2N1cmF0ZSBiZWNhdXNlIG9mIHRoZSBsYWNrIG9mIGRhdGEsIGJ1dCBhdCBsZWFzdCB3ZSBjYW4gc2VlIHRoYXQgdGhlcmUgaXMgc29tZSByZWxhdGlvbiBiZXR3ZWVuIHRoZXNlIHBhcmFtZXRlcnMgYW5kIGxpZmUgZXhwZWN0YW5jeSBhbmQgaXQncyBjbGVhciBhcyBldmVyeXRoaW5nIHJlZHVjZXMgdG8gaWYgY291bnRyeSBjYW4gcHJvdmlkZSBpdHMgcmVzaWRlbnRzIHdpdGggd29yaywgbWVkaWNpbmUgYW5kIGdvb2QgZmluYW5jZSBjYXBpdGFsICh3aGljaCBkZXBlbmRzIG9uIGpvYiksIHRoZW4gdGhvc2UgcGVvcGxlIGNhbiBjb3ZlciBhbGwgdGhlaXIgbmVlZCB0byBsaXZlIGxvbmcgYW5kIGhlYWx0aHkgbGlmZS4NCg==